package br.ufal.compiladores;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Compilador {
    BufferedReader buf;
    FileInputStream file;
    ArrayList<String> palavrasArquivo;
    String strLine;
    private int strColum;
    private int linha;
    int linhaAtual = 0;
    int contadorLinha;
    Token tk;

    /**
     * Add File Path
     * 
     * @param filePath
     * @throws IOException
     */
    public Compilador(String filePath) throws IOException {
        strColum = 0;
        linha = 0;
        palavrasArquivo = new ArrayList<String>();

        FileInputStream fstream;
        try {
            fstream = new FileInputStream(filePath);
            DataInputStream in = new DataInputStream(fstream);
            buf = new BufferedReader(new InputStreamReader(in));

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            while (buf.ready()) {
                palavrasArquivo.add(buf.readLine());
            }
        }

    }
    /**
     * 
     * @return Class Token
     * @throws IOException
     */
    public Token letoken() throws IOException {
        String palavra = "";
        ArrayList<String> separadores = new ArrayList<String>();
        separadores.add("(");
        separadores.add(")");
        separadores.add("{");
        separadores.add("}");
        separadores.add("[");
        separadores.add("]");
        separadores.add("=");
        separadores.add("/");
        separadores.add("*");
        separadores.add("-");
        separadores.add("!");
        separadores.add("+");
        separadores.add(" ");
        separadores.add("    ");
        separadores.add(";");
        separadores.add(",");
        separadores.add("<");
        separadores.add(">");

        strLine = palavrasArquivo.get(linha);
        if (strLine != null) {
            if (strColum == strLine.length() || strColum > strLine.length()) {
                strColum = 0;
                linha++;
            }
            if (linha >= palavrasArquivo.size()) {
                return null;
            }
            strLine = palavrasArquivo.get(linha);

            while (strColum < strLine.length()) {
                char caracter = strLine.charAt(strColum);
                char nextCaracter;

                if (separadores.contains(caracter + "")) {
                    if (palavra.equals("inicio")) {
                        tk = new Token(palavra, TokenTypes.Inicio, linha,
                                strColum - palavra.length());
                        break;
                    } else if (palavra.equals("enquanto")) {
                        tk = new Token(palavra, TokenTypes.Enquanto, linha,
                                strColum - palavra.length());
                        break;
                    } else if (palavra.equals("se")) {
                        tk = new Token(palavra, TokenTypes.Se, linha, strColum
                                - palavra.length());
                        break;
                    } else if (palavra.equals("senao")) {
                        tk = new Token(palavra, TokenTypes.Senao, linha,
                                strColum - palavra.length());
                        break;

                    } else if (palavra.equals("palavra")) {
                        tk = new Token(palavra, TokenTypes.Palavra, linha,
                                strColum - palavra.length());
                        break;

                    } else if (palavra.equals("inteiro")) {
                        tk = new Token(palavra, TokenTypes.Inteiro, linha,
                                strColum - palavra.length());
                        break;
                    } else if (palavra.equals("real")) {
                        tk = new Token(palavra, TokenTypes.Real, linha,
                                strColum - palavra.length());
                        break;
                    } else if (palavra.equals("retorno")) {
                        tk = new Token(palavra, TokenTypes.Retorno, linha,
                                strColum - palavra.length());
                        break;

                    } else if (palavra.equals("saida")) {
                        tk = new Token(palavra, TokenTypes.Saida, linha,
                                strColum - palavra.length());
                        break;

                    } else if (palavra.equals("||")) {
                        tk = new Token(palavra, TokenTypes.Logico_or, linha,
                                strColum - palavra.length());
                        break;

                    } else if (palavra.equals("&&")) {
                        tk = new Token(palavra, TokenTypes.Logico_and, linha,
                                strColum - palavra.length());
                        break;

                    } else {
                        if (palavra != "") {
                            Pattern stringConst = Pattern
                                    .compile("([a-zA-Z_]([a-zA-Z_0-9])*)");
                            Pattern cadeiaConst = Pattern
                                    .compile("(\")(([a-zA-Z_]([a-zA-Z_0-9])*)|(\\-)?[0-9]+(\\.[0-9]+)?(e-[0-9]+)?)(\")");
                            Pattern numRealConst = Pattern
                                    .compile("(\\-)?[0-9]+(\\.[0-9]+)(e-[0-9]+)?");
                            Pattern numConst = Pattern
                                    .compile("(\\-)?[0-9]+(e-[0-9]+)?");

                            Matcher pesquisaString = stringConst
                                    .matcher(palavra);
                            Matcher pesquisaCadeia = cadeiaConst
                                    .matcher(palavra);
                            Matcher pesquisaNum = numConst.matcher(palavra);
                            Matcher pesquisaNumReal = numRealConst
                                    .matcher(palavra);

                            if (pesquisaString.matches()) {
                                tk = new Token(palavra, TokenTypes.Id, linha,
                                        strColum - palavra.length());
                                break;
                            } else if (pesquisaNumReal.matches()) {
                                tk = new Token(palavra, TokenTypes.Num_real,
                                        linha, strColum - palavra.length());
                                break;
                            } else if (pesquisaNum.matches()) {
                                tk = new Token(palavra, TokenTypes.Numeral,
                                        linha, strColum - palavra.length());
                                break;
                            } else if (pesquisaCadeia.matches()) {
                                tk = new Token(palavra,
                                        TokenTypes.Cadeia_Caracteres, linha,
                                        strColum - palavra.length());
                                break;
                            }
                        }

                    }

                    switch (caracter) {
                    case '{':
                        tk = new Token(caracter + "", TokenTypes.Achaves,
                                linha, strColum);
                        break;
                    case '}':
                        tk = new Token(caracter + "", TokenTypes.Fchaves,
                                linha, strColum);
                        break;
                    case '(':
                        tk = new Token(caracter + "", TokenTypes.Aparenteses,
                                linha, strColum);
                        break;
                    case ')':
                        tk = new Token(caracter + "", TokenTypes.Fparenteses,
                                linha, strColum);
                        break;
                    case '[':
                        // tk = new Token(palavra + "",
                        // TokenTypes.Id,linha,strColum);
                        tk = new Token(caracter + "", TokenTypes.AColchetes,
                                linha, strColum);
                        break;
                    case ']':
                        tk = new Token(caracter + "", TokenTypes.FColchetes,
                                linha, strColum);
                        break;
                    case ';':
                        tk = new Token(caracter + "", TokenTypes.Finstrucao,
                                linha, strColum);
                        break;
                    case ',':
                        tk = new Token(caracter + "", TokenTypes.Virgula,
                                linha, strColum);
                        break;
                    case '=':
                        nextCaracter = strLine.charAt(strColum + 1);
                        if (nextCaracter == '=') {
                            tk = new Token(Character.toString(caracter)
                                    + Character.toString(nextCaracter),
                                    TokenTypes.Relacional, linha, strColum);
                            strColum++;
                        } else {
                            tk = new Token(caracter + "",
                                    TokenTypes.Sinal_tribuicao, linha, strColum);
                        }

                        break;
                    case '+':
                        tk = new Token(caracter + "", TokenTypes.Sinal_de_soma,
                                linha, strColum);
                        break;
                    case '*':
                        tk = new Token(caracter + "", TokenTypes.Sinal_de_mult,
                                linha, strColum);
                        break;
                    case '/':
                        tk = new Token(caracter + "", TokenTypes.Sinal_de_div,
                                linha, strColum);
                        break;
                    case '-':
                        tk = new Token(caracter + "", TokenTypes.Sinal_de_sub,
                                linha, strColum);
                        break;
                    case '<':
                        nextCaracter = strLine.charAt(strColum + 1);
                        if (nextCaracter == '=') {
                            tk = new Token(Character.toString(caracter)
                                    + Character.toString(nextCaracter),
                                    TokenTypes.Relacional, linha, strColum);
                            strColum++;
                        } else {
                            tk = new Token(caracter + "",
                                    TokenTypes.Relacional, linha, strColum);
                        }

                        break;
                    case '>':
                        nextCaracter = strLine.charAt(strColum + 1);
                        if (nextCaracter == '=') {
                            tk = new Token(Character.toString(caracter)
                                    + Character.toString(nextCaracter),
                                    TokenTypes.Relacional, linha, strColum);
                            strColum++;
                        } else {
                            tk = new Token(caracter + "",
                                    TokenTypes.Relacional, linha, strColum);
                        }

                        break;
                    case '!':
                        nextCaracter = strLine.charAt(strColum + 1);
                        if (nextCaracter == '=') {
                            tk = new Token(Character.toString(caracter)
                                    + Character.toString(nextCaracter),
                                    TokenTypes.Diferente, linha, strColum);
                            strColum++;
                        } else {
                            tk = new Token(caracter + "",
                                    TokenTypes.Logico_not, linha, strColum);
                        }
                    default:
                        break;
                    }

                    palavra = "";
                } else {
                    if (caracter != ' ') {
                        palavra += caracter;
                    }
                }
                strColum++;
            }
        }
        return tk;
    }
}
